package org.ccay.core.expression;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;


/**
 * 消息表达式估值器
 * 
 * Created 2011-9-19
 * @author chaowangbang
 * @version:
 */
public class MessageEvaluator {
	
	/** 目标方法的缓存，避免重复的字节码解析 **/
	private Map<Method, Method> targetMethodCache = new ConcurrentHashMap<Method, Method>();
	
	/** Expression的缓存，提高性能 **/
	private Map<Method, Expression> expressionCache = new ConcurrentHashMap<Method, Expression>();
	
	private ParameterNameDiscoverer paramNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
	
	private TemplateParserContext parserContext;
	
	private ExpressionParser parser;
	
	public MessageEvaluator() {
		this.parserContext = new TemplateParserContext("{", "}");
		this.parser = new SpelExpressionParser();
	}
	
	public String evaluate(InvocationContext invocationContext, String messageTemplate) {
		Method auditedMethod = invocationContext.getMethod();
		if(!expressionCache.containsKey(auditedMethod)) {
			Expression exp = parser.parseExpression(messageTemplate, parserContext);
			expressionCache.put(auditedMethod, exp);
		}
		Expression expression = expressionCache.get(auditedMethod);
		EvaluationContext evaluationContext = createEvaluationContext(invocationContext);
		//16418 减复杂度
		if(invocationContext.getParameterValues().length>0 &&invocationContext.getMethod().getParameterTypes().length>0 && invocationContext.getMethod().getParameterTypes()[0]==List.class){  //濡傛灉鍙傛暟绫诲瀷涓篖ist 骞朵笖List.size()>0
			return evalListObject(invocationContext,messageTemplate,evaluationContext);
		}else{
			return evalOtherObject(invocationContext,messageTemplate,evaluationContext,expression);
		}
	}
	/**
	 * 
	 * 处理list对象
	 * @param invocationContext
	 * @param messageTemplate
	 * @param evaluationContext
	 * @return
	 * Created：2013-1-11
	 * @author chaowangbang
	 */
	private String evalListObject(InvocationContext invocationContext, String messageTemplate,EvaluationContext evaluationContext){
		if(messageTemplate.indexOf("{") == -1){
			//无el表达式转换
			return messageTemplate;
		}
		StringBuffer msg=new StringBuffer();
		List<Object> list=(List<Object>) invocationContext.getParameterValues()[0];  //获取List对象
		if(!list.isEmpty()){
			for(int index=0;index<list.size();index++){   //遍历对象转换表达式中的对象属性
				Object obj=list.get(index);
				msg.append(evalObject(obj, messageTemplate.replaceAll("#", ""), evaluationContext));
			}
		}
		return interceptmessageTemplate(messageTemplate)+msg.toString()+interceptEndmessageTemplate(messageTemplate);
	}
	/**
	 * 
	 * 处理其他类型对象
	 * @param invocationContext
	 * @param messageTemplate
	 * @param evaluationContext
	 * @return
	 * Created：2013-1-11
	 * @author chaowangbang
	 */
	private String evalOtherObject(InvocationContext invocationContext, String messageTemplate,EvaluationContext evaluationContext,Expression expression){
		if(invocationContext.getParameterValues().length>0){//invocationContext不存在参数值的情况
			Object obj=invocationContext.getParameterValues()[0];
			if(messageTemplate.indexOf("{")>-1 && obj!=null){//如果存在转换的表达式
					return interceptmessageTemplate(messageTemplate)+evalObject(obj, messageTemplate, evaluationContext)+interceptEndmessageTemplate(messageTemplate);
			}else{
				return messageTemplate;
			}
		}else{
			if(messageTemplate.indexOf("{")>-1){
				return expression.getValue(evaluationContext, String.class);
			}else{
				return messageTemplate;
			}
		}
	}
	/**
	 * Object对象表达式转换
	 * @author chaowangbang
	 * @since 2012-09-21
	 * @param obj
	 * @param messageTemplate
	 * @param evaluationContext
	 * @return
	 */
	private String evalObject(Object obj,String messageTemplate,EvaluationContext evaluationContext){
		StringBuffer msg=new StringBuffer();
		String[] splitMsg=splitmessageTemplate(messageTemplate);
		for(int index=0;index<splitMsg.length;index++){
			Expression exp = parser.parseExpression(splitMsg[index], parserContext);//转换表达式
			if(splitMsg.length==1){
				msg=msg.append(exp.getValue(evaluationContext,obj));
			}else if(index==splitMsg.length-1){
				msg=msg.append(exp.getValue(evaluationContext,obj)).append(";");
			}else{
				msg=msg.append(exp.getValue(evaluationContext,obj)).append(",");  //分离显示对象属性
			}
		}
		return msg.toString();
	}
	
	

	/**
	 * @author chaowangbang
	 * @since  2012-09-18
	 * @param messageTemplate
	 * @return
	 * 截取第一个"{"前面的字符
	 */
	private String interceptmessageTemplate(String messageTemplate){
		int flagIndex=messageTemplate.indexOf("{");
		if(flagIndex>-1){//是否存在配置参数
			return messageTemplate.substring(0,flagIndex);
		}else{
			return "";
		}
	}
	
	/**
	 * @author chaowangbang
	 * @since  2012-09-18
	 * @param messageTemplate
	 * @return
	 * 截取最后"}"后面的字符
	 */
	public String interceptEndmessageTemplate(String messageTemplate){
		int flagIndex=messageTemplate.lastIndexOf("}");
		if(flagIndex>-1){//是否存在配置参数
			return messageTemplate.substring(flagIndex+1);
		}else{
			return "";
		}
	}
	
	
	/**
	 * @author chaowangbang
	 * @since 2012-09-19
	 * 截取配置要求记录的属性参数
	 * @param messageTemplate
	 * @return
	 */
	private String[] splitmessageTemplate(String messageTemplate){
		int flagIndex=messageTemplate.indexOf("{");
		if(flagIndex>-1){ //是否存在配置参数
			String splitmessage=messageTemplate.substring(flagIndex);
			String[] splitMsg=splitmessage.split(","); //分割参数
			return splitMsg;
		}else{
			return new String[]{};
		}
	}
	
	
	private EvaluationContext createEvaluationContext(InvocationContext invocationContext) {
		return new LazyParamAwareEvaluationContext(
				invocationContext,
				paramNameDiscoverer,
				targetMethodCache);
	}
}
